# 导包
import os
import pandas as pd
import numpy as np
import datetime
from utils.log import Logger
from sklearn.metrics import mean_absolute_error, accuracy_score
import matplotlib.ticker as mick
import joblib
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score, roc_auc_score
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

plt.rcParams['font.family'] = 'SimHei'
plt.rcParams['font.size'] = 15
"""
人才流失预测类
"""


class AttritionPredict(object):
    def __init__(self, file_path):
        # 1.定义日志文件名
        logfile_name = 'ten_predict_' + datetime.datetime.now().strftime('%Y%m%d%H%M%S')
        # 2.创建日志对象
        self.logger = Logger('../', logfile_name).get_logger()
        # 3.获取数据源
        self.data_source = pd.read_csv(file_path)


def data_processing(am: AttritionPredict):
    # 0.获取数据源,数据备份
    data = am.data_source.copy()
    # 1.删除无关列
    data = data.drop(['EmployeeNumber', 'Over18', 'StandardHours'], axis=1)
    return data


def feature_engineering(data):
    """
    特征工程
    :param am: 人才流失模型类
    :return: 特征数据,特征列名
    """
    # 特征工程
    # data["age_group"] = pd.cut(data["Age"], bins=[0, 35, 45, 100], labels=[0, 1, 2]).astype(int)
    # data['JobSatisfaction_NumCompaniesWorked'] = data["JobSatisfaction"] / (data["NumCompaniesWorked"] + 1)
    # data["MonthlyIncome_TotalWorkingYears"] = data["MonthlyIncome"] / (data["TotalWorkingYears"] + 100)
    # data['Gender_MaritalStatus'] = data["Gender"] + "_" + data["MaritalStatus"]
    # department_dict = {
    #     "Human Resources": ["Human Resources"],
    #     "Research & Development": ["Life Sciences", "Medical", "Technical Degree"], "Sales": ["Marketing"]
    # }
    # data['Professional_counterparts'] = data.apply(
    #     lambda row: 1 if row['EducationField'] in department_dict.get(row['Department'], []) else 0,
    #     axis=1
    # )
    # data["YearsAtCompany_YearsInCurrentRole"] = data['YearsAtCompany'] - data['YearsInCurrentRole']
    # data['YearsInCurrentRole_YearsAtCompany'] = data['YearsInCurrentRole'] / (data['YearsAtCompany'] + 1)
    # data["EnvironmentSatisfaction_JobSatisfaction"] = data['EnvironmentSatisfaction'] * data['JobSatisfaction']
    data = pd.get_dummies(data, dtype=int)

    return data


def pred_feature_extract(data_source, logger):
    """
    定义：预测数据解析方法
    :param data_source:测试数据源
    :param logger:日志对象
    :return:训练数据
    """
    # 1. 获取特征、标签
    y = data['Attrition']
    x = data.drop('Attrition', axis=1)
    return x, y


def prediction_plot(y, y_pre):
    # 1 创建画布
    fig = plt.figure(figsize=(30, 20))
    # todo 第一个子图，饼图-真实
    # 2获取流失人数、不流失人数
    data_lose1 = len(y[y == 1])
    data_exist1 = len(y[y == 0])
    # 3设置饼图参数
    sizes1 = [data_lose1, data_exist1]
    labels = ['流失比例', '不流失比例']
    # 4绘制饼图
    ax1 = fig.add_subplot(221)
    ax1.pie(sizes1, labels=labels, autopct='%1.1f%%')
    # 5设置标题
    ax1.set_title('人才流失情况占比图(真实)')

    # todo 第二个子图，饼图-预测
    # 2获取流失人数、不流失人数
    data_lose2 = len(y_pre[y_pre == 1])
    data_exist2 = len(y_pre[y_pre == 0])
    # 3设置饼图参数
    sizes2 = [data_lose2, data_exist2]
    labels = ['流失比例', '不流失比例']
    # 4绘制饼图
    ax2 = fig.add_subplot(222)
    ax2.pie(sizes2, labels=labels, autopct='%1.1f%%')
    # 5设置标题
    ax2.set_title('人才流失情况占比图(预测)')

    # todo 第三个子图-柱状图-真实
    # 2柱状图x轴，y轴
    categories1 = ['流失', '不流失']
    values = [data_lose1, data_exist1]
    # 4绘制柱状图
    ax3 = fig.add_subplot(223)
    ax3.bar(categories1, values)
    # 5设置标题
    ax3.set_title('人才流失情况柱状图(真实)')

    # todo 第四个子图-柱状图-预测
    # 2柱状图x轴，y轴
    categories1 = ['流失', '不流失']
    values = [data_lose2, data_exist2]
    # 4绘制柱状图
    ax4 = fig.add_subplot(224)
    ax4.bar(categories1, values)
    # 5设置标题
    ax4.set_title('人才流失情况柱状图(真实)')

    # 6 保存图像
    plt.savefig("../data/fig/人才流失情况_预测.png")

    # 7 图像展示
    plt.show()


if __name__ == '__main__':
    # todo 1.人才流失预测类测试
    ap = AttritionPredict(r'../data/test.csv')
    # ap.logger.info("测试日志")
    # ap.data_source.info()
    # todo 2.数据预处理
    data = data_processing(ap)
    # todo 3.特征工程测试
    data = feature_engineering(data)
    # data.info()
    # todo 4.加载模型对象
    model = joblib.load(r"../model/xgb_20251026.pkl")
    # todo 5.获取要预测的数据
    x, y = pred_feature_extract(data, ap.logger)
    # transfer = StandardScaler()
    # x = transfer.fit_transform(x)
    # todo 6.模型预测
    y_pre = model.predict(x)
    y_pre = np.where(y_pre > 0.163, 1, 0)
    # todo 7.模型评估
    print(f"准确率：{accuracy_score(y, y_pre)}")
    print(f"精确率：{precision_score(y, y_pre)}")
    print(f"的召回率：{recall_score(y, y_pre)}")
    print(f"f1-score：{f1_score(y, y_pre)}")
    print(f"AUC：{roc_auc_score(y, y_pre, average='macro')}")
    # print(y_pre)
    # todo 8.绘图
    prediction_plot(y, y_pre)
